#include "transContentFuncCallTargetReachable.hpp"

/////////////////////////////////////////////////////////////////////////////////
/// construct packet to stack, use data fifo
/// because this packet has less than 24 bytes, so just use static buffer rather than memory pool
///
///		request packet content format
///		name | length | mainCode | subCode | localPort |target |
///		 len |	  2   |   1      |    1    |   4       |  8    |
///    offset|    0   |   2      |    3    |   4       |  8    |
/// parameter:
///		this method use object field as parameters
///
/// return:
///		E_TRANC_ParamError: need value is invalidate
///		E_TRANC_TIMEOUT: the method timeout
///		E_TRANC_NONBLOCK: the method use sync style
///		result: the query result
/////////////////////////////////////////////////////////////////////////////////////
int TransContentFuncCallTargetReachable::targetReachable(){
	char buffer[20]={0};
	timespec ts = TransContentAssis::TimeTp2Ts(timeout);
	debug_enter();
	if(localPort <= 0 || target.serial_id <= 0){
		logd_error("TransContentFuncCallTargetReachable::targetReachable==> parameter error");
		return E_TRANC_ParamError;
	}
	memset(buffer, 0x00, 20);
	*(short*(buffer)) = (short)16;
	buffer[2] = message_type_inner_functionCall_targetReachable_request;
	*(NodeAddr*(buffer+4)) = localPort;
	*(NodeAddr*(buffer+8)) = target;

	/// send to stack, use data fifo
	TransContentDispatcher::getInstance()->sendDataDataToStack(buffer, 16);

	/// wait or reutrn
	if(tracb != NULL){
		logd_info("TransContentFuncCallTargetReachable::targetReachable==> callback not null, use sync style, the caller return");
		return E_TRANC_NONBLOCK;
	}

	/// wait the condtion value
	pthread_mutex_lock(&waitMutex);
	pthread_cond_timedwait(&waitCond, & waitMutex, &tes);
	pthread_mutex_unlock(&waitMutex);
	canBeRemoved = 1;
	return result;
}

//////////////////////////////////////////////////////////////////////////////////
/// target reachable response
///		extract reachable information from the packet
///
///		request packet content format
///		name | length | mainCode | subCode | localPort |target | result |
///		 len |	  2   |   1      |    1    |   4       |  8    |   1    |
///    offset|    0   |   2      |    3    |   4       |  8    |   16   |
/// parameters:
///		buffer: the packet contain the response information
///		index: the buffer index int he memory pool index
/// return:
///		RESPONSE_RESULT_DELETE_RECORD: delete the record in the port manager
///////////////////////////////////////////////////////////////////////////////////
int TransContentFuncCallTargetReachable::response(char* buffer, int index){
	debug_enter();
	pthread_t pid;
	int localPort = *((int*)(buffer+4));
	NodeAddr target = *((NodeAddr*)(buffer+8));
	result = buffer[16];

	/// if use sync style, start the new route
	if(tracb != NULL){
		logd_info("response use sync style");
		pthread_create(&pid, NULL, finishedRoute, this);
		pthread_detach(pid);
	}else{
		logd_info("response use block style");
		pthread_mutex_lock(&waitMutex);
		pthread_cond_signal(&waitCond);
		pthread_mutex_unlock(&waitMutex);
	}
	sleep(SYNC_METHOD_RETURN_TIME);
	canBeRemoved = 1;
	logd_info("after sleep %d sleep, now return and destroy the record", SYNC_METHOD_RETURN_TIME);
	return RESPONSE_RESULT_DELETE_RECORD;
}
